#include <stdio.h>
#include <stdlib.h>

#include <jpeglib.h>

#include "_image.h"
#include "_jpeg.h"
#include "_types.h"
#include "image.h"
#include "_osd.h"
#include "window.h"


/* Enables or disables debug output */
#ifdef __DEBUG
#define __D(fmt, args...) fprintf(stderr, "JPEG Debug: " fmt, ## args)
#else
#define __D(fmt, args...)
#endif

#define __E(fmt, args...) fprintf(stderr, "JPEG Error: " fmt, ## args)

int jpeg_create(FILE *file, image *imgp) {
    struct jpeg_decompress_struct cinfo;
    JSAMPARRAY buffer;
    int pos;
    int row_stride;
    struct jpeg_error_mgr jerr;
    int x;
    unsigned short *dst;
    int r, g, b;

    if (file == NULL) {
        __E("Failed to create jpeg image file\n");
        return JPEG_FAILURE;
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, file);
    jpeg_read_header(&cinfo, TRUE);

    jpeg_start_decompress(&cinfo);

    row_stride = cinfo.output_width * cinfo.output_components;

    buffer = (*cinfo.mem->alloc_sarray)
            ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);

    imgp->bufp = malloc((row_stride * cinfo.output_height * 2) / 3);
    imgp->alphabufp = malloc(cinfo.output_width * cinfo.output_height);
    imgp->w = cinfo.output_width;
    imgp->h = cinfo.output_height;

    if (imgp->bufp == NULL || imgp->alphabufp == NULL) {
        __E("Failed to allocate memory for jpeg image\n");
        return JPEG_FAILURE;
    }

    dst = imgp->bufp;

    while (cinfo.output_scanline < cinfo.output_height) {
        jpeg_read_scanlines(&cinfo, (JSAMPARRAY) buffer, 1);

        for (x = 0; x < cinfo.output_width; x++) {
            if (cinfo.output_components == 1) { // Grayscale
                r = buffer[0][x] * (1 << 5) / (1 << 8);
                g = buffer[0][x] * (1 << 6) / (1 << 8);
                b = buffer[0][x] * (1 << 5) / (1 << 8);
            } else { // RGB
                pos = x * cinfo.output_components;
                r = buffer[0][pos + 0] * (1 << 5) / (1 << 8);
                g = buffer[0][pos + 1] * (1 << 6) / (1 << 8);
                b = buffer[0][pos + 2] * (1 << 5) / (1 << 8);
            }
            dst[x] = b | (g << 5) | (r << 11);
        }
        dst += cinfo.output_width;
    }

    memset(imgp->alphabufp, 255, imgp->w * imgp->h);

    jpeg_finish_decompress(&cinfo);
    fclose(file);

    return JPEG_SUCCESS;
}
/*
int jpeg_delete(image *imgp) {
    free(imgp->bufp);

    return JPEG_SUCCESS;
}
*/
